package com.innovation.ic.cyz.web.controller.cyz;

import com.innovation.ic.b1b.framework.util.PathUtils;
import com.innovation.ic.b1b.framework.util.StringUtils;
import com.innovation.ic.cyz.base.pojo.variable.cyz.UploadVideoPojo;
import com.innovation.ic.cyz.base.pojo.global.ApiResult;
import com.innovation.ic.cyz.base.pojo.global.ServiceResult;
import com.innovation.ic.cyz.base.pojo.variable.cyz.UploadImagePojo;
import com.innovation.ic.cyz.web.controller.AbstractController;
import com.jcraft.jsch.SftpException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

@Api(value = "文件API", tags = "FileController")
@RestController
@RequestMapping("/api/v1/file")
public class FileController extends AbstractController {
    private static final Logger log = LoggerFactory.getLogger(FileController.class);

    /**
     * 上传图片
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ApiOperation(value = "上传图片")
    @ApiImplicitParam(name = "category", value = "图片分类", required = true, dataType = "Long")
    @RequestMapping(value = "/uploadImage", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<ApiResult<UploadImagePojo>> uploadImage(@RequestParam("category") String category,
                                                                  HttpServletRequest request, HttpServletResponse response) throws IOException, SftpException {
        // 检查图片分类
        if (category == null || category.isEmpty()) {
            ApiResult<UploadImagePojo> apiResult = new ApiResult<>();
            apiResult.setSuccess(Boolean.FALSE);
            apiResult.setCode(HttpStatus.OK.value());
            apiResult.setMessage("未接收到category参数");
            return new ResponseEntity<ApiResult<UploadImagePojo>>(apiResult, HttpStatus.OK);
        }

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        String originalFileName = file.getOriginalFilename();
        InputStream input = file.getInputStream();

        // 检查是否有文件
        if (originalFileName == null || originalFileName.isEmpty()) {
            ApiResult<UploadImagePojo> apiResult = new ApiResult<>();
            apiResult.setSuccess(Boolean.FALSE);
            apiResult.setCode(HttpStatus.OK.value());
            apiResult.setMessage("未接收到文件");
            return new ResponseEntity<ApiResult<UploadImagePojo>>(apiResult, HttpStatus.OK);
        }

        // 生成新的文件名
        String fileExt = PathUtils.getFileExtension(originalFileName);
        String newFileName = getRandomFileName();
        if (!fileExt.isEmpty()) {
            newFileName += "." + fileExt;
        }

        // 获取年月日字符串
        Calendar now = Calendar.getInstance();
        String year = Integer.toString(now.get(Calendar.YEAR));
        String month = Integer.toString(now.get(Calendar.MONTH) + 1);
        month = StringUtils.padRight(month, 2, '0');
        String day = Integer.toString(now.get(Calendar.DAY_OF_MONTH));
        day = StringUtils.padRight(day, 2, '0');

        // 相对路径名
        String relativeDirName = category + "/" + year + "/" + month + "/" + day; // 前后都已有斜杠

        // 传ftp
        serviceHelper.getSftpChannelManager().upload(ftpAccountConfig.getImageSaveBasePath() + relativeDirName, newFileName, input);

        UploadImagePojo result = new UploadImagePojo();
        result.setOriginalFileName(originalFileName);
        result.setRelativeUrl(relativeDirName + "/" + newFileName);
        result.setAbsoluteUrl(ftpAccountConfig.getImageUrlBasePath() + relativeDirName + "/" + newFileName);

        ApiResult<UploadImagePojo> apiResult = new ApiResult<>();
        apiResult.setSuccess(Boolean.TRUE);
        apiResult.setCode(HttpStatus.OK.value());
        apiResult.setResult(result);
        apiResult.setMessage(ServiceResult.SELECT_SUCCESS);
        return new ResponseEntity<ApiResult<UploadImagePojo>>(apiResult, HttpStatus.OK);
    }

    /**
     * 上传视频
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ApiOperation(value = "上传视频")
    @ApiImplicitParam(name = "category", value = "视频分类", required = true, dataType = "Long")
    @RequestMapping(value = "/uploadVideo", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<ApiResult<UploadVideoPojo>> uploadVideo(@RequestParam("category") String category,
                                                                  HttpServletRequest request, HttpServletResponse response) throws IOException, SftpException {
        // 检查视频分类
        if (category == null || category.isEmpty()) {
            ApiResult<UploadVideoPojo> apiResult = new ApiResult<>();
            apiResult.setSuccess(Boolean.FALSE);
            apiResult.setCode(HttpStatus.OK.value());
            apiResult.setMessage("未接收到category参数");
            return new ResponseEntity<ApiResult<UploadVideoPojo>>(apiResult, HttpStatus.OK);
        }

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        String originalFileName = file.getOriginalFilename();
        InputStream input = file.getInputStream();

        // 检查是否有文件
        if (originalFileName == null || originalFileName.isEmpty()) {
            ApiResult<UploadVideoPojo> apiResult = new ApiResult<>();
            apiResult.setSuccess(Boolean.FALSE);
            apiResult.setCode(HttpStatus.OK.value());
            apiResult.setMessage("未接收到文件");
            return new ResponseEntity<ApiResult<UploadVideoPojo>>(apiResult, HttpStatus.OK);
        }

        // 生成新的文件名
        String fileExt = PathUtils.getFileExtension(originalFileName);
        String newFileName = getRandomFileName();
        if (!fileExt.isEmpty()) {
            newFileName += "." + fileExt;
        }

        // 获取年月日字符串
        Calendar now = Calendar.getInstance();
        String year = Integer.toString(now.get(Calendar.YEAR));
        String month = Integer.toString(now.get(Calendar.MONTH) + 1);
        month = StringUtils.padRight(month, 2, '0');
        String day = Integer.toString(now.get(Calendar.DAY_OF_MONTH));
        day = StringUtils.padRight(day, 2, '0');

        // 相对路径名
        String relativeDirName = category + "/" + year + "/" + month + "/" + day; // 前后都已有斜杠

        // 传ftp
        serviceHelper.getSftpChannelManager().upload(ftpAccountConfig.getVideoSaveBasePath() + relativeDirName, newFileName, input);

        UploadVideoPojo result = new UploadVideoPojo();
        result.setOriginalFileName(originalFileName);
        result.setRelativeUrl(relativeDirName + "/" + newFileName );
        result.setAbsoluteUrl(ftpAccountConfig.getVideoUrlBasePath() + relativeDirName + "/" + newFileName);

        ApiResult<UploadVideoPojo> apiResult = new ApiResult<>();
        apiResult.setSuccess(Boolean.TRUE);
        apiResult.setCode(HttpStatus.OK.value());
        apiResult.setResult(result);
        apiResult.setMessage(ServiceResult.SELECT_SUCCESS);
        return new ResponseEntity<ApiResult<UploadVideoPojo>>(apiResult, HttpStatus.OK);
    }

    /**
     * 获取随机文件名
     *
     * @return
     */
    private String getRandomFileName() {
        String guid = java.util.UUID.randomUUID().toString().replace("-", "");

        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String timeString = simpleDateFormat.format(date);

        StringBuilder sb = new StringBuilder();
        sb.append(timeString).append("-").append(guid);
        return sb.toString();
    }

    /**
     * 下载文件(从minio中获取)
     */
    @ApiOperation(value = "下载文件")
    @ApiImplicitParam(name = "path", value = "文件相对路径", required = true, dataType = "String")
    @RequestMapping(value = "/downloadFile/**", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity downloadFile(HttpServletRequest request, HttpServletResponse response) {
        String uri = request.getRequestURI();
        String beginFlag = "downloadFile/";
        int downloadFileIndex = uri.indexOf(beginFlag);
        if (downloadFileIndex <= -1) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }

        String filePath = uri.substring(downloadFileIndex + beginFlag.length());
        String fileName = PathUtils.getFileNameWithExtensionFromUrl(uri);

        try {
            InputStream is = serviceHelper.getMinioManager().getObject(minioPropConfig.getBucketName(), filePath);
            OutputStream os = response.getOutputStream();
            byte[] bytes = StreamUtils.copyToByteArray(is);
            response.reset();
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition", "attachment;filename="
                    + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            response.addHeader("Content-Length", "" + bytes.length);
            os.write(bytes);
            os.flush();
            return new ResponseEntity(HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity(HttpStatus.NOT_FOUND);
        }

    }


    /**
     * @Description: 上传附件
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/11/1015:00
     */
    @ApiOperation(value = "上传附件")
    @PostMapping(value = "/uploadProtocol")
    @ResponseBody
    public ResponseEntity<ApiResult<UploadVideoPojo>> uploadProtocol(HttpServletRequest request) throws IOException, SftpException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        String originalFileName = file.getOriginalFilename();
        InputStream input = file.getInputStream();
        // 检查是否有文件
        if (originalFileName == null || originalFileName.isEmpty()) {
            ApiResult<UploadVideoPojo> apiResult = new ApiResult<>();
            apiResult.setSuccess(Boolean.FALSE);
            apiResult.setCode(HttpStatus.OK.value());
            apiResult.setMessage("未接收到文件");
            return new ResponseEntity<ApiResult<UploadVideoPojo>>(apiResult, HttpStatus.OK);
        }

        // 生成新的文件名
        String fileExt = PathUtils.getFileExtension(originalFileName);
        String newFileName = getRandomFileName();
        if (!fileExt.isEmpty()) {
            newFileName += "." + fileExt;
        }
        // 传ftp
//        SftpUtils sftp = new SftpUtils(ftpAccountConfig.getUsername(), ftpAccountConfig.getPassword(), ftpAccountConfig.getHost(), ftpAccountConfig.getPort());
//        sftp.login();
//        sftp.upload(ftpAccountConfig.getProtocolSaveBasePath() + relativeDirName, newFileName, input);
//        sftp.logout();
        //文档需要用minio上传
        ApiResult<UploadVideoPojo> apiResult = new ApiResult<>();
        try {
            serviceHelper.getMinioManager().putObject(minioPropConfig.getBucketName(),  newFileName, input, Long.valueOf(input.available()), file.getContentType());
        } catch (Exception e) {
            log.info("附件上传失败,e:{}",e);
            e.printStackTrace();
            apiResult.setSuccess(Boolean.TRUE);
            apiResult.setCode(HttpStatus.BAD_REQUEST.value());
            apiResult.setMessage("附件上传失败");
            return  new ResponseEntity<ApiResult<UploadVideoPojo>>(apiResult, HttpStatus.OK);
        }

        UploadVideoPojo result = new UploadVideoPojo();
        result.setOriginalFileName(originalFileName);
        result.setRelativeUrl(newFileName );
        result.setAbsoluteUrl(minioPropConfig.getUrlBasePath()  + newFileName);

        apiResult.setSuccess(Boolean.TRUE);
        apiResult.setCode(HttpStatus.OK.value());
        apiResult.setResult(result);
        apiResult.setMessage(ServiceResult.SELECT_SUCCESS);
        return new ResponseEntity<ApiResult<UploadVideoPojo>>(apiResult, HttpStatus.OK);
    }

    /**
     * @Description: 删除图片
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/11/1014:25
     */
    @ApiOperation(value = "删除图片")
    @ApiImplicitParam(name = "relativePath" ,value = "图片相对路径",required = true,dataType = "string")
    @GetMapping("/deleteImg")
    public ResponseEntity<HttpStatus> deleteImg(@RequestParam("relativePath") String relativePath){
        try {
            this.delete(relativePath,ftpAccountConfig.getImageSaveBasePath());
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (Exception e) {
            log.error("删除图片异常：｛｝",e);
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }


    /**
     * @Description: 删除视频
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/11/1014:25
     */
    @GetMapping("/deleteVideo")
    @ApiOperation("删除视频")
    @ApiImplicitParam(name = "relativePath" ,value = "视频相对路径",required = true,dataType = "string")
    public ResponseEntity<HttpStatus> deleteVideo(@RequestParam("relativePath") String relativePath){
        try {
            this.delete(relativePath,ftpAccountConfig.getVideoSaveBasePath());
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (Exception e) {
            log.error("删除视频异常：｛｝",e);
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    /**
     * @Description: 删除视频
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/11/1014:25
     */
    @GetMapping("/deleteProtocol")
    @ApiOperation("删除附件")
    @ApiImplicitParam(name = "relativePath" ,value = "附件相对路径",required = true,dataType = "string")
    public ResponseEntity<HttpStatus> deleteProtocol(@RequestParam("relativePath") String relativePath){
        try {
            this.delete(relativePath,ftpAccountConfig.getProtocolSaveBasePath());
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (Exception e) {
            log.error("删除附件异常：｛｝",e);
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }


    /**
     * @Description: 删除文件函数
     * @Params:
     * @Return:
     * @Author: Mr.myq
     * @Date: 2022/11/1014:44
     */
    private void delete(String relativePath,String fileBaseUrl){
        Assert.isTrue(StringUtils.isNotEmpty(relativePath),"路径不能为空");
        int index = relativePath.lastIndexOf("/");
        if(index <= 0)
            throw new RuntimeException("路径不合法,未包含路径和文件名。");

        String imageUrlBasePath = fileBaseUrl  + relativePath;
        log.info("imageUrlBasePath: " +imageUrlBasePath);
        File f = new File(imageUrlBasePath);
        if(f.exists()) {
            boolean delete = f.delete();
            Assert.isTrue(delete,"文件在其他位置已打开暂时无法删除");
        }else {
            throw new RuntimeException("文件不存在");
        }
    }

}
